package cn.koala.key.common.utils;


import cn.seed.common.core.ResultCode;
import cn.seed.common.core.ServiceException;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @description:订单号生成器
 *
 * 系统的单号有两种：
 * 1. getNumberHeader(shopId, orderType) + generateCode(4)
 * 2. genNumber(String orderType, String numberHeader, String lastOrderNo)
 * 即后四位有的是字符，有的是数字。
 *
 * 截止到2019-3-28日，出库单表leave_stock的订单类型中6和13的单号后四位是字符
 * 7~12的单号后四位是数字。
 *
 * 编写相关单号生成逻辑时，要注意这点
 *
 * @author 刘旭
 * @time 2018年4月9日 上午10:20:32
 * 
 */
public class OrderNoGenerator {
	/** 订单类型:发货单*/
	public static final String ORDER_TYPE_DEMAND = "YH";
	/** 订单类型:采购单*/
	public static final String ORDER_TYPE_PURCHASE = "DD";
	/** 订单类型:发货单*/
	public static final String ORDER_TYPE_SHIP = "FH";
	/** 订单类型:退货单*/
	public static final String ORDER_TYPE_RETURN = "TH";
	/** 订单类型:入库单*/
	public static final String ORDER_TYPE_STOCK = "RK";
	/** 订单类型:出库单*/
	public static final String ORDER_TYPE_LEAVE = "CK";
	/** 订单类型:盘点单*/
	public static final String ORDER_TYPE_TAKE = "PD";
	/** 订单类型:报废单*/
	public static final String ORDER_TYPE_SCRAP = "BF";
	/** 订单类型:调整单*/
	public static final String ORDER_TYPE_ADJUSTMENT = "TZ";
	/** 订单类型:调拨单*/
	public static final String ORDER_TYPE_ALLOT = "DB";

	/**
	 * 订货单号
	 */
	public static final String ORDER_TYPE_INDENT = "DH";
	/**
	 * 领料单
	 */
	public static final String ORDER_TYPE_LL = "LL";
	/**
	 * 退料单
	 */
	public static final String ORDER_TYPE_TL = "TL";

	private static final String DATE_FORMATE_YYYYMMMDD = "yyyyMMdd";

	private OrderNoGenerator() {
		throw new UnsupportedOperationException("Utility class can not be instantiated.");
	}

	private static String[] chars = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D",
			"E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
			"Z" };

	/**
	 * 
	 * @Description:生成指定位数随机字符
	 * @param length
	 *            位数
	 * @return String
	 * @exception:
	 * @author: wws
	 * @time:2018年5月8日 下午4:18:58
	 */
	private static String generateCode(int length) {
		StringBuilder shortBuffer = new StringBuilder();
		String uuid = UUID.randomUUID().toString().replace("-", "");
		for (int i = 0; i < length; i++) {
			String str = uuid.substring(i * 4, i * 4 + 4);
			int x = Integer.parseInt(str, 16);
			shortBuffer.append(chars[x % chars.length]);
		}
		return shortBuffer.toString();
	}

	/**
	 * 
	 * @Description:生成18位单号
	 * @return 4位shopId + 2位订单类型编码 + 8位年月日 + 4位随机字符 例：0004CK20180508WCU5 String
	 * @exception:
	 * @author: wws
	 * @time:2018年5月8日 下午4:29:34
	 */
	public static String generateOrderNo(int shopId, String orderType) {
		return getNumberHeader(shopId, orderType) + generateCode(4);
	}

	public static String genNumber(String orderType, String numberHeader, String lastOrderNo) {
		int demandOrderIndex = 1;
		if (null != lastOrderNo) {
			try {
				demandOrderIndex = Integer.parseInt(lastOrderNo.substring(14)) + 1;
			} catch (Exception e) {
				switch (orderType) {
				case ORDER_TYPE_DEMAND:
					throw new ServiceException(ResultCode.FAIL, "上一个要货单号存在错误，无法继续生成新的订单号");
				case ORDER_TYPE_PURCHASE:
					throw new ServiceException(ResultCode.FAIL, "上一个采购订单号存在错误，无法继续生成新的订单号");
				case ORDER_TYPE_SHIP:
					throw new ServiceException(ResultCode.FAIL, "上一个发货单号存在错误，无法继续生成新的订单号");
				case ORDER_TYPE_STOCK:
					throw new ServiceException(ResultCode.FAIL, "上一个入库单号存在错误，无法继续生成新的订单号");
				default:
					throw e;
				}
			}
		}
		return numberHeader + getFourLenNo(demandOrderIndex);
	}

	public static String getNumberHeader(int shopId, String orderType) {
		return getFourLenNo(shopId) + orderType + getDateStr();
	}

	private static String getFourLenNo(int index) {
		if (index < 10) {
			return "000" + index;
		} else if (index < 100) {
			return "00" + index;
		} else if (index < 1000) {
			return "0" + index;
		} else {
			return String.valueOf(index);
		}
	}

	private static String getDateStr() {
		return new SimpleDateFormat(DATE_FORMATE_YYYYMMMDD).format(new Date());
	}

}
